﻿/*
 * @Descripttion: 
 * @version: 
 * @Author: MichaelHu
 * @Date: 2022-02-15 15:25:48
 * @LastEditors: MichaelHu
 * @LastEditTime: 2022-02-23 11:21:37
 */
#include "lua_obj.h"

typedef struct lv_anim_mydata
{
    int exec_cb_ref;
    int ready_cb_ref;
    void *obj;
} lv_anim_user_data_t;

static int lua_auto_gc(lua_State *L)
{
    /* lv_obj_t *lv_obj = *(lv_obj_t **)luaL_checkudata(L, 1, META_ANIM);
    luaL_argcheck(L, lv_obj != NULL, 1, "invalid user data");
    if (lv_obj)
    {
        lv_obj_del(lv_obj);
    }
    return 0;*/
}

static int lua_lv_anim_set_var(lua_State *L)
{
    LUA_USER_PRINT(__func__);
    lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);
    void *var = *(lv_obj_t **)lua_touserdata(L, 2);
    lv_anim_set_var(a, var);
    
    return 0;
}

static void lua_lv_anim_exec_cb(void *var, lv_coord_t value)
{
    lv_anim_t *a = lv_anim_get(var, lua_lv_anim_exec_cb);
    lua_State *L = lua_getstate();
    lv_anim_user_data_t *user_data = a->user_data;

    if (user_data->exec_cb_ref == 0)
        return;

    lua_rawgeti(L, LUA_REGISTRYINDEX, user_data->exec_cb_ref);
    if (lua_isfunction(L, -1)) //判断栈顶
    {
        lua_pushinteger(L, value);
        lua_call(L, 1, 0);
    }
}

static int lua_lv_anim_set_exec_cb(lua_State *L)
{
    LUA_USER_PRINT(__func__);
    lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);
    luaL_argcheck(L, lua_isfunction(L, 2), 2, "Must be function");

    lv_anim_user_data_t *user_data = (lv_anim_user_data_t *)lua_newuserdata(L, sizeof(lv_anim_user_data_t));
    lv_anim_set_user_data(a, user_data);

    if (user_data->exec_cb_ref != 0)
    {
        luaL_unref(L, LUA_REGISTRYINDEX, user_data->exec_cb_ref);
    }
    if (lua_isfunction(L, 2))
    {
        lua_settop(L, 2);
        user_data->exec_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
        lv_anim_set_exec_cb(a, lua_lv_anim_exec_cb);
    }
    else
    {
        user_data->exec_cb_ref = 0;
        lv_anim_set_exec_cb(a, NULL);
    }
    return 0;
}

static int lua_lv_anim_set_time(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);
    uint32_t duration = luaL_checkinteger(L, 2);
	lv_anim_set_time(a, duration);

	return 0;
}

static int lua_lv_anim_set_delay(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);
    uint32_t delay = luaL_checkinteger(L, 2);
	lv_anim_set_delay(a, delay);

	return 0;
}

static int lua_lv_anim_set_values(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);
    int32_t start = luaL_checkinteger(L, 2);
    int32_t end = luaL_checkinteger(L, 3);
	lv_anim_set_values(a, start, end);

	return 0;
}

static int lua_lv_anim_set_custom_exec_cb(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_set_path_cb(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);
    const char* tp = luaL_checkstring(L, 2);
    
    if (!strcmp("path_linear", tp)) {
        lv_anim_set_path_cb(a, lv_anim_path_linear);
    }
    else if (!strcmp("path_ease_in", tp)) {
        lv_anim_set_path_cb(a, lv_anim_path_ease_in);
    }
    else if (!strcmp("path_ease_out", tp)) {
        lv_anim_set_path_cb(a, lv_anim_path_ease_out);
    }
    else if (!strcmp("ease_in_out", tp)) {
        lv_anim_set_path_cb(a, lv_anim_path_ease_in_out);
    }
    else if (!strcmp("path_overshoot", tp)) {
        lv_anim_set_path_cb(a, lv_anim_path_overshoot);
    }
    else if (!strcmp("path_bounce", tp)) {
        lv_anim_set_path_cb(a, lv_anim_path_bounce);
    }
    else if (!strcmp("path_step", tp)) {
        lv_anim_set_path_cb(a, lv_anim_path_step);
    }

	return 0;
}

static int lua_lv_anim_set_start_cb(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_set_get_value_cb(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_set_ready_cb(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_set_playback_time(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);
    uint32_t time = luaL_checkinteger(L, 2);
	lv_anim_set_playback_time(a, time);

	return 0;
}

static int lua_lv_anim_set_playback_delay(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);
    uint32_t delay = luaL_checkinteger(L, 2);
	lv_anim_set_playback_delay(a, delay);

	return 0;
}

static int lua_lv_anim_set_repeat_count(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);
    uint16_t cnt = luaL_checkinteger(L, 2);
	lv_anim_set_repeat_count(a, cnt);

	return 0;
}

static int lua_lv_anim_set_repeat_delay(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);
    uint32_t delay = luaL_checkinteger(L, 2);
	lv_anim_set_repeat_delay(a, delay);

	return 0;
}

static int lua_lv_anim_set_early_apply(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_set_user_data(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_start(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);
    lv_anim_start(a);

	return 0;
}

static int lua_lv_anim_get_delay(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_get_playtime(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_get_user_data(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_del(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_del_all(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_get(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_custom_del(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_custom_get(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_count_running(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_speed_to_time(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);
    int32_t start = luaL_checkinteger(L, 2);
    int32_t end = luaL_checkinteger(L, 3);
	lv_anim_speed_to_time(a, start, end);

	return 0;
}

static int lua_lv_anim_refr_now(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_path_linear(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_path_ease_in(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_path_ease_out(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_path_ease_in_out(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_path_overshoot(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_path_bounce(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}

static int lua_lv_anim_path_step(lua_State *L)
{
	LUA_USER_PRINT(__func__);
	lv_anim_t *a = (lv_anim_t *)luaL_checkudata(L, 1, META_ANIM);

	return 0;
}
static const struct luaL_Reg arraylib_m[] = {
	{"set_var", lua_lv_anim_set_var},
	{"set_exec_cb", lua_lv_anim_set_exec_cb},
	{"set_time", lua_lv_anim_set_time},
	{"set_delay", lua_lv_anim_set_delay},
	{"set_values", lua_lv_anim_set_values},
	{"set_custom_exec_cb", lua_lv_anim_set_custom_exec_cb},
	{"set_path_cb", lua_lv_anim_set_path_cb},
	{"set_start_cb", lua_lv_anim_set_start_cb},
	{"set_get_value_cb", lua_lv_anim_set_get_value_cb},
	{"set_ready_cb", lua_lv_anim_set_ready_cb},
	{"set_playback_time", lua_lv_anim_set_playback_time},
	{"set_playback_delay", lua_lv_anim_set_playback_delay},
	{"set_repeat_count", lua_lv_anim_set_repeat_count},
	{"set_repeat_delay", lua_lv_anim_set_repeat_delay},
	{"set_early_apply", lua_lv_anim_set_early_apply},
	{"set_user_data", lua_lv_anim_set_user_data},
	{"start", lua_lv_anim_start},
	{"get_delay", lua_lv_anim_get_delay},
	{"get_playtime", lua_lv_anim_get_playtime},
	{"get_user_data", lua_lv_anim_get_user_data},
	{"del", lua_lv_anim_del},
	{"del_all", lua_lv_anim_del_all},
	{"get", lua_lv_anim_get},
	{"custom_del", lua_lv_anim_custom_del},
	{"custom_get", lua_lv_anim_custom_get},
	{"count_running", lua_lv_anim_count_running},
	{"speed_to_time", lua_lv_anim_speed_to_time},
	{"refr_now", lua_lv_anim_refr_now},
	{NULL, NULL}};

static int help(lua_State *L)
{
    uint16_t n = sizeof(arraylib_m) / sizeof(struct luaL_Reg);

    for (int i = 0; i < n - 1; i++)
    {
        printf("%s\r\n", arraylib_m[i].name);
    }
    return 1;
}
static const struct luaL_Reg arraylib_f[] = {
    {"help", help},
    {NULL, NULL}};

static const struct luaH_Reg_enum_string arraylib_string[] = {
    {"path_linear", "path_linear"}, 
    {"path_ease_in", "path_ease_in"}, 
    {"path_ease_out", "path_ease_out"}, 
    {"path_ease_in_out", "path_ease_in_out"}, 
    {"path_overshoot", "path_overshoot"}, 
    {"path_bounce", "path_bounce"}, 
    {"path_step", "path_step"}, 
    {NULL, NULL}};

LUALIB_API int lua_lv_anim_funinit(lua_State *L)
{
    luaL_newlib(L, arraylib_f);
    luaL_newmetatable(L, META_ANIM); /* create metatable for file handles */
    lua_pushvalue(L, -1);            /* push metatable */
    lua_setfield(L, -2, "__index");  /* metatable.__index = metatable */
    luaL_setfuncs(L, arraylib_m, 0); /* add file methods to new metatable */
    lua_pop(L, 1);                   /* pop new metatable */
    
    lua_pushnumber(L, LV_ANIM_REPEAT_INFINITE);
    lua_setfield(L, -2, "LV_ANIM_REPEAT_INFINITE");

    add_enum_string(L, arraylib_string);
    return 1;
}
